#include "softtimer.h"
#include "stdlib.h"
#include "bsp.h"

soft_timer_t soft_timer[MAX_SOFT_TIMER_ID+1];

timer_t timer_ticks = 0;

void soft_timer_init(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
  TIM_DeInit(TIM4);    
	NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_TimeBaseStructure.TIM_Prescaler = 840-1;     //100k            	     	
  TIM_TimeBaseStructure.TIM_Period = 200-1;        //200           2ms              	
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;                
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  
  TIM_ClearFlag(TIM4,TIM_FLAG_Update);                         
  TIM_Cmd(TIM4, ENABLE);                                        
  TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);                    	
}


void soft_timer_lock(void)
{
}

void soft_timer_unlock(void)
{
}

bool soft_timer_set(u8 timer_id,u32 time_ms,u32 period,timer_callback_t *call_back)	
{
	u32 ticks=0;
	if(timer_id>MAX_SOFT_TIMER_ID)
		return false;
	if(time_ms==0)
		return false;
	ticks = time_ms/STIMER_POLLING_CLK_MS;
	if(ticks==0)
		ticks=1;
	if(period==0)
		period=1;
	soft_timer_lock();
	soft_timer[timer_id].ticks = ticks;
	soft_timer[timer_id].ticks_reload = ticks;
	soft_timer[timer_id].period = period;
	soft_timer[timer_id].timer_callback = call_back;
	soft_timer[timer_id].running = true;
	soft_timer_unlock();
	return true;
}

void soft_timer_cancel(u8 timer_id)	
{
	if(timer_id>MAX_SOFT_TIMER_ID)
		return;
	soft_timer_lock();
	soft_timer[timer_id].ticks=0;
	soft_timer[timer_id].timer_callback = NULL;
	soft_timer[timer_id].running = false;
	soft_timer[timer_id].ticks_reload=0;
	soft_timer[timer_id].period=0;
	soft_timer_unlock();
}

bool is_stimer_run(u8 timer_id)
{
	bool temp;
	soft_timer_lock();
	temp=soft_timer[timer_id].running;
	soft_timer_unlock();
	return temp;
}


void soft_timer_polling(void)
{
	u8 i=0;
	bool running=false;
	u32 ticks_remain=0;
	timer_callback_t *call_back=NULL;
	for(i=0;i<=MAX_SOFT_TIMER_ID;i++)
	{
		soft_timer_lock();
		running = soft_timer[i].running;
		ticks_remain = soft_timer[i].ticks;
		soft_timer_unlock();
		if(running!=true)
			continue;
		if(ticks_remain>0)
		{
			soft_timer_lock();
			soft_timer[i].ticks--;
			ticks_remain--;
			soft_timer_unlock();
		}
		if(ticks_remain==0)
		{
			soft_timer_lock();
			call_back = soft_timer[i].timer_callback;
			if(soft_timer[i].period&&(soft_timer[i].period!=MAX_PERIOD))
				soft_timer[i].period--;
			if(soft_timer[i].period)
			{
				soft_timer[i].ticks = soft_timer[i].ticks_reload;
			}
			else
			{
				soft_timer[i].running = false;
				soft_timer[i].timer_callback =NULL;
			}
			soft_timer_unlock();
			if(call_back!=NULL)
				call_back(NULL);
		}
	}	
	timer_ticks ++;
}




timer_t __get_timer_ticks(void)
{
	timer_t tmp;
	TIM_ITConfig(TIM4,TIM_IT_Update,DISABLE);
	tmp = timer_ticks;
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
	return tmp;
}



timer_t get_one_timer(u32 time_ms)
{ 
	timer_t ticks;
	ticks = time_ms/STIMER_POLLING_CLK_MS;
	if(ticks==0)
		ticks=1;
	return __get_timer_ticks() + ticks;
}


u8 check_timer(timer_t timer)
{
	timer_t cur_time;

	cur_time = __get_timer_ticks();
	
	if(cur_time >= timer) return 1;
	else return 0;
}

void TIM4_IRQHandler(void)  
{
  TIM_ClearITPendingBit(TIM4, TIM_IT_Update);         
	soft_timer_polling();
	
}










